/*
 * @Author: hongbin
 * @Date: 2021-10-12 07:42:23
 * @LastEditTime: 2021-10-21 07:36:08
 * @Description: 定时提醒
 * @FilePath: /hongbin_xyz_web/pages/timingReminder.tsx
 */
import {
  ChangeEventHandler,
  FC,
  ReactElement,
  useRef,
  useState,
  useEffect,
  useCallback,
} from "react";
import styled, { css } from "styled-components";
import { ActiveLateY, flexCenter } from "../components/BUI/styled";
import { ThemeBgcAndText } from "../components/BUI/View/ThemeView";
import { ContainerCss, fadeIn } from "../components/commentStyled";
import { LoadButton, FlexDiv } from "../components/BUI";
import { CancelIcon } from "../components/BUI/Icon";
import SEO from "../layout/SEO";
import { sendMailCode, verificationMailCode } from "../api/authApi";
import LoadIcon from "../components/BUI/Icon/LoadIcon";
import * as Task from "../api/timeTaskApi";
import Create from "../components/TimeTask/Create";
import UpdateForm from "../components/TimeTask/UpdateForm";

interface IProps {}

const mailREG = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;

const initQuestIndex = -1;

const TYPES = ["创建", "删除", "更改", "查询"];

const TYPE = {
  0: { input: "提醒内容" },
  1: { input: "输入邮箱号" },
  2: { input: "输入邮箱号" },
  3: { input: "输入邮箱号" },
};

type Tt = typeof TYPE;

const TimingReminder: FC<IProps> = (): ReactElement => {
  const [openBindMail, setOpenBindMail] = useState(false);
  const [typeKey, setTypeKey] = useState(0);
  const [countDown, setCountDown] = useState(0);
  const [interval, setInterval] = useState("0.5");
  const [loading, setLoading] = useState({
    sendCode: false,
    verification: false,
  });
  const [encryptedInfo, setEncryptedInfo] = useState("");
  const [questIndex, setQuestIndex] = useState(initQuestIndex); //哪个task item正在执行请求操作
  const [taskList, setTaskList] = useState<Task.ITask[]>([]);
  const [updateId, setUpdateId] = useState<string>("");
  const [uploading, setUploading] = useState<boolean>(false); //更新中
  const inputRef = useRef<HTMLInputElement>(null);
  const mailRef = useRef<HTMLInputElement>(null);
  const codeRef = useRef<HTMLInputElement>(null);

  const handleSelect: ChangeEventHandler<HTMLSelectElement> = useCallback(e => {
    setInterval(e.currentTarget.selectedOptions[0].value);
  }, []);

  const handleClickMarkTrue = () => {
    if (inputRef && inputRef.current && inputRef.current.value) {
      setOpenBindMail(true);
    } else console.log("输入提醒内容");
  };

  useEffect(() => {
    if (countDown) {
      setTimeout(() => {
        setCountDown(count => count - 1);
      }, 1000);
    }
  }, [countDown]);

  const handleSendVerificationCode = useCallback(async () => {
    //邮箱格式正确
    const mail = mailRef.current;
    if (mail && mailREG.test(mail.value)) {
      setLoading(prev => ({ ...prev, sendCode: true }));
      const result = await sendMailCode(mail.value, "timingReminder");
      if (result) {
        // 保存加密信息
        setEncryptedInfo(result);
        setCountDown(60);
      } else console.log("发送失败");
      setLoading(prev => ({ ...prev, sendCode: false }));
    } else console.log("检查邮箱格式");
  }, []);

  const createTask = async () => {
    const { data } = await Task.createTimeTask({
      content: inputRef.current!.value,
      interval,
      mail: mailRef.current!.value,
    });
    if (data) {
      console.log("定时任务", data);
    }
  };

  const queryTask = async () => {
    const { data } = await Task.queryTimeTaskByMail({
      mail: mailRef.current!.value,
    });
    if (data) {
      console.log("查询结果:", data);
      setTaskList(data.list);
    }
  };

  /**
   * 最终提交验证码和信息 后执行函数
   */
  const verification = (passBack: () => Promise<void>) => async () => {
    const code = codeRef.current as HTMLInputElement;
    const mail = mailRef.current as HTMLInputElement;

    if (!mail.value || !code.value)
      return console.log("请检查验证码或邮箱是否填写");
    if (loading.verification) return console.log("在加载了.");

    setLoading(prev => ({ ...prev, verification: true }));
    const verificationCode = await verificationMailCode({
      code: code.value,
      encryptedInfo,
      type: "timingReminder",
    });
    console.log("验证码通过:", verificationCode);
    verificationCode && (await passBack());
    setLoading(prev => ({ ...prev, verification: false }));
  };

  const handleDeleteTaskItem = (id: string, index: number) => () => {
    if (questIndex !== initQuestIndex) return console.log("等待其他请求");
    setQuestIndex(index);
    Task.deleteTimeTask(id).then(({ data }) => {
      if (data) {
        console.log("删除成功");
        setTaskList(prov => prov.filter(item => item._id !== id));
      }
      setQuestIndex(initQuestIndex);
    });
  };

  const handleUpdateTaskItem = (id: string) => () => {
    setUpdateId(id);
  };

  const handleCancelUpdate = useCallback(() => {
    setUpdateId("");
  }, []);

  const handleUpdate = useCallback(
    async (content: string) => {
      setUploading(true);
      const item = {
        _id: updateId,
        interval,
        content,
      };
      const { data } = await Task.updateTimeTask(item);
      console.log("task:", item, data);
      if (data) {
        console.log("更新成功");
        queryTask();
        handleCancelUpdate();
      }
      setUploading(false);
    },
    [handleCancelUpdate, interval, updateId]
  );

  return (
    <Container type={typeKey}>
      <SEO title="定时提醒" logo="/timer.svg" />
      <FlexDiv style={{ overflow: "hidden" }}>
        {TYPES.map((text, index) => (
          <TabBarSpan
            onClick={() => setTypeKey(index)}
            selected={index === typeKey}
            key={index}
          >
            {text}任务
          </TabBarSpan>
        ))}
      </FlexDiv>
      <RemindInput>
        <input
          ref={inputRef}
          placeholder={typeKey ? "输入邮箱号" : "提醒内容"}
        />
      </RemindInput>
      <RemindTime>
        {typeKey === 0 && (
          <Create
            onClick={
              openBindMail ? verification(createTask) : handleClickMarkTrue
            }
            handleSelect={handleSelect}
            loading={loading.verification}
          />
        )}

        <Mask typeKey={!!typeKey} open={openBindMail}>
          <CancelIcon onClick={() => setOpenBindMail(false)} />
          <FlexDiv style={{ marginLeft: "8rem" }} items="center">
            <input ref={mailRef} placeholder="输入邮箱号" />
            <LoadButton
              width="7rem"
              onClick={countDown ? undefined : handleSendVerificationCode}
              margin
              loading={loading.sendCode}
            >
              {countDown ? `${countDown}s可再次发送` : "发送验证码"}
            </LoadButton>
          </FlexDiv>
          <input ref={codeRef} placeholder="输入验证码" />
          {!typeKey ? (
            <span>每天晚10点到凌晨7点不执行任务,请注意休息</span>
          ) : (
            <LoadButton
              loading={loading.verification}
              onClick={verification(queryTask)}
              width="10rem"
            >
              查询任务列表
            </LoadButton>
          )}
          {typeKey
            ? taskList.map(({ _id, content, interval }, index) => (
                <TaskItem key={_id}>
                  <code>{interval}小时</code>
                  <span>{content}</span>
                  {typeKey < 3 ? (
                    <LoadButton
                      loading={questIndex === index}
                      onClick={
                        typeKey === 1
                          ? handleDeleteTaskItem(_id, index)
                          : handleUpdateTaskItem(_id)
                      }
                      width="5rem"
                    >
                      {typeKey === 1 ? "删除" : "更改"}
                    </LoadButton>
                  ) : null}
                </TaskItem>
              ))
            : null}
          {updateId ? (
            <UpdateForm
              handleSelect={handleSelect}
              loading={uploading}
              onUpdate={handleUpdate}
              handleCancelUpdate={handleCancelUpdate}
            />
          ) : null}
        </Mask>
      </RemindTime>
    </Container>
  );
};

export default TimingReminder;

const TaskItem = styled.div`
  box-shadow: 2px 2px 10px #ccc;
  width: 25rem;
  margin-top: 1rem;
  border-radius: 0.3rem;
  padding: 0 0.3rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  overflow: hidden;
  & > span {
    padding: 0.5rem;
    width: 15rem;
    flex: 1;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
  & > code {
    width: 4rem;
  }
`;

const hoverStyle = css`
  background: var(--primary-color);
  color: #fff;
  box-shadow: 0px 0px 5px 0px #55f;
`;

const TabBarSpan = styled.span<{ selected: boolean }>`
  padding: 0.8rem;
  letter-spacing: 2px;
  margin: 0.2rem;
  cursor: pointer;
  transition: all 0.3s linear;
  transition-property: background, color, box-shadow, transform;
  border-radius: 5px;
  flex: 1;
  text-align: center;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  /* max-width: 3rem; */

  :hover {
    ${hoverStyle};
  }
  :active {
    background: #000;
    transform: translateY(0.2rem);
  }
  ${({ selected }) => selected && hoverStyle};
`;

const Mask = styled.div<{ open: boolean; typeKey: boolean }>`
  display: flex;
  align-items: center;
  flex-direction: column;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  /* background: #000000; */
  background: inherit;
  display: ${({ open }) => (open ? `flex` : "none")};
  animation: ${fadeIn} 0.3s linear;

  input {
    margin: 2rem;
  }

  & > svg {
    position: absolute;
    right: 1rem;
    top: 1rem;
    width: 2rem;
    height: 2rem;
    cursor: pointer;
    ${ActiveLateY};
    path {
      fill: var(--primary-color);
    }
  }

  & > span:last-child {
    color: #999;
    position: absolute;
    bottom: 1rem;
  }

  ${({ typeKey }) =>
    typeKey &&
    css`
      display: flex;
      & > svg {
        display: none;
      }
    `};
`;

const RemindTime = styled.div`
  transition: transform 0.3s linear;
  height: var(--second-height);
  flex-direction: column;
  justify-content: space-evenly !important;
  position: relative;
  overflow: hidden;

  @media (max-width: ${props => props.theme.media.phone}) {
    ${Mask} {
      & > div:nth-child(2) {
        margin-left: 0 !important;
        margin-top: 5rem;
        flex-direction: column;
        button {
          width: auto;
        }
      }
    }
  }
`;

const RemindInput = styled.div`
  transition: transform 0.3s linear, opacity 0.2s linear;
  height: 10rem;
`;

const Container = styled.div<{ type: number }>`
  ${ContainerCss};
  padding: 1rem;
  & > div {
    ${flexCenter};
    ${ThemeBgcAndText};
    border-radius: 0.5rem;
    margin-top: 2rem;
  }
  input {
    border-radius: 0.2rem;
    width: 25rem;
    height: 3rem;
    border: none;
    background: #eee;
    padding: 0.5rem;
    outline: none;
    box-shadow: 6px 4px 12px #666;
  }
  --second-height: 20rem;
  @media (max-width: ${props => props.theme.media.phone}) {
    --second-height: 40rem;
    input,
    ${TaskItem} {
      width: 20rem;
    }
  }
  ${({ type }) =>
    type &&
    css`
      ${RemindInput} {
        transform: translateY(calc(var(--second-height) + 2rem));
        opacity: 0;
      }
      ${RemindTime} {
        transform: translateY(-12rem);
        height: 100vh;
      }
    `};
`;
